// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team

// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or(at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#ifndef VBA_ELF_H
#define VBA_ELF_H

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

enum LocationType
{
	LOCATION_register,
	LOCATION_memory,
	LOCATION_value
};

#define DW_ATE_boolean       0x02
#define DW_ATE_signed        0x05
#define DW_ATE_unsigned      0x07
#define DW_ATE_unsigned_char 0x08

struct ELFHeader
{
	u32 magic;
	u8  clazz;
	u8  data;
	u8  version;
	u8  pad[9];
	u16 e_type;
	u16 e_machine;
	u32 e_version;
	u32 e_entry;
	u32 e_phoff;
	u32 e_shoff;
	u32 e_flags;
	u16 e_ehsize;
	u16 e_phentsize;
	u16 e_phnum;
	u16 e_shentsize;
	u16 e_shnum;
	u16 e_shstrndx;
};

struct ELFProgramHeader
{
	u32 type;
	u32 offset;
	u32 vaddr;
	u32 paddr;
	u32 filesz;
	u32 memsz;
	u32 flags;
	u32 align;
};

struct ELFSectionHeader
{
	u32 name;
	u32 type;
	u32 flags;
	u32 addr;
	u32 offset;
	u32 size;
	u32 link;
	u32 info;
	u32 addralign;
	u32 entsize;
};

struct ELFSymbol
{
	u32 name;
	u32 value;
	u32 size;
	u8  info;
	u8  other;
	u16 shndx;
};

struct ELFBlock
{
	int length;
	u8 *data;
};

struct ELFAttr
{
	u32 name;
	u32 form;
	union
	{
		u32       value;
		char *    string;
		u8 *      data;
		bool      flag;
		ELFBlock *block;
	};
};

struct ELFAbbrev
{
	u32        number;
	u32        tag;
	bool       hasChildren;
	int        numAttrs;
	ELFAttr *  attrs;
	ELFAbbrev *next;
};

enum TypeEnum
{
	TYPE_base,
	TYPE_pointer,
	TYPE_function,
	TYPE_void,
	TYPE_array,
	TYPE_struct,
	TYPE_reference,
	TYPE_enum,
	TYPE_union
};

struct Type;
struct Object;

struct FunctionType
{
	Type *  returnType;
	Object *args;
};

struct Member
{
	char *    name;
	Type *    type;
	int       bitSize;
	int       bitOffset;
	int       byteSize;
	ELFBlock *location;
};

struct Struct
{
	int     memberCount;
	Member *members;
};

struct Array
{
	Type *type;
	int   maxBounds;
	int * bounds;
};

struct EnumMember
{
	char *name;
	u32   value;
};

struct Enum
{
	int         count;
	EnumMember *members;
};

struct Type
{
	u32      offset;
	TypeEnum type;
	char *   name;
	int      encoding;
	int      size;
	int      bitSize;
	union
	{
		Type *        pointer;
		FunctionType *function;
		Array *       array;
		Struct *      structure;
		Enum *        enumeration;
	};
	Type *next;
};

struct Object
{
	char *    name;
	int       file;
	int       line;
	bool      external;
	Type *    type;
	ELFBlock *location;
	u32       startScope;
	u32       endScope;
	Object *  next;
};

struct Function
{
	char *    name;
	u32       lowPC;
	u32       highPC;
	int       file;
	int       line;
	bool      external;
	Type *    returnType;
	Object *  parameters;
	Object *  variables;
	ELFBlock *frameBase;
	Function *next;
};

struct LineInfoItem
{
	u32   address;
	char *file;
	int   line;
};

struct LineInfo
{
	int           fileCount;
	char **       files;
	int           number;
	LineInfoItem *lines;
};

struct ARange
{
	u32 lowPC;
	u32 highPC;
};

struct ARanges
{
	u32     offset;
	int     count;
	ARange *ranges;
};

struct CompileUnit
{
	u32          length;
	u8 *         top;
	u32          offset;
	ELFAbbrev ** abbrevs;
	ARanges *    ranges;
	char *       name;
	char *       compdir;
	u32          lowPC;
	u32          highPC;
	bool         hasLineInfo;
	u32          lineInfo;
	LineInfo *   lineInfoTable;
	Function *   functions;
	Function *   lastFunction;
	Object *     variables;
	Type *       types;
	CompileUnit *next;
};

struct DebugInfo
{
	u8 *     debugfile;
	u8 *     abbrevdata;
	u8 *     debugdata;
	u8 *     infodata;
	int      numRanges;
	ARanges *ranges;
};

struct Symbol
{
	char *name;
	int   type;
	int   binding;
	u32   address;
	u32   value;
	u32   size;
};

extern u32 elfReadLEB128(u8 *, int *);
extern s32 elfReadSignedLEB128(u8 *, int *);
extern bool elfRead(const char *, int &, FILE *f);
extern bool elfGetSymbolAddress(char *, u32 *, u32 *, int *);
extern char *elfGetAddressSymbol(u32);
extern char *elfGetSymbol(int, u32 *, u32 *, int *);
extern void elfCleanUp();
extern bool elfGetCurrentFunction(u32, Function **, CompileUnit **c);
extern bool elfGetObject(char *, Function *, CompileUnit *, Object * *);
extern bool elfFindLineInUnit(u32 *, CompileUnit *, int);
extern bool elfFindLineInModule(u32 *, char *, int);
u32 elfDecodeLocation(Function *, ELFBlock *, LocationType *);
u32 elfDecodeLocation(Function *, ELFBlock *, LocationType *, u32);
int elfFindLine(CompileUnit *unit, Function *func, u32 addr, char * *);

#endif // VBA_ELF_H
